package cn.clj;

import cn.clj.cell.CljCell;
import cn.clj.cell.CljCellType;
import cn.clj.func.CljFunc;
import cn.clj.func.CljFuncParam;
import cn.clj.func.CljFuncParamList;
import cn.clj.func.MyCljFunc;
import cn.clj.recur.CljRecur;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;

/**
 * clojure 的解释器
 * */
public class MyClojureInterp {
    // 全局 function 或者 宏展开
    private Hashtable<String, MyCljFunc> funcs = new Hashtable<String, MyCljFunc>();
    // 全局变量
    private Hashtable<String, Object> params = new Hashtable<String, Object>();

    private MyClojureReader clojureReader;

    public MyClojureInterp(String txt)
    {
        CljLinesFromString myIInput = new CljLinesFromString(txt);
        CljCharIterator myCharIterator = new CljCharIterator(myIInput);
        CljLexer lexer = new CljLexer(myCharIterator);
        this.clojureReader = new MyClojureReader(lexer);
    }

    public MyClojureInterp()
    {
    }

    public static Number add(Number num1, Number num2) {
        if (num1 instanceof Integer || num1 instanceof Double || num1 instanceof Float || num1 instanceof Long || num1 instanceof Short || num1 instanceof Byte) {
            return num1.doubleValue() + num2.doubleValue();
        } else if (num1 instanceof BigInteger) {
            return ((BigInteger) num1).add(new BigInteger(num2.toString()));
        } else if (num1 instanceof BigDecimal) {
            return ((BigDecimal) num1).add(new BigDecimal(num2.toString()));
        } else {
            throw new IllegalArgumentException("Unsupported Number type");
        }
    }

    public static Number subtraction(Number num1, Number num2) {
        if (num1 instanceof Integer || num1 instanceof Double || num1 instanceof Float || num1 instanceof Long || num1 instanceof Short || num1 instanceof Byte) {
            return num1.doubleValue() - num2.doubleValue();
        } else if (num1 instanceof BigInteger) {
            return ((BigInteger) num1).subtract(new BigInteger(num2.toString()));
        } else if (num1 instanceof BigDecimal) {
            return ((BigDecimal) num1).subtract(new BigDecimal(num2.toString()));
        } else {
            throw new IllegalArgumentException("Unsupported Number type");
        }
    }

    public static Number multiplication(Number num1, Number num2) {
        if (num1 instanceof Integer || num1 instanceof Double || num1 instanceof Float || num1 instanceof Long || num1 instanceof Short || num1 instanceof Byte) {
            return num1.doubleValue() * num2.doubleValue();
        } else if (num1 instanceof BigInteger) {
            return ((BigInteger) num1).multiply(new BigInteger(num2.toString()));
        } else if (num1 instanceof BigDecimal) {
            return ((BigDecimal) num1).multiply(new BigDecimal(num2.toString()));
        } else {
            throw new IllegalArgumentException("Unsupported Number type");
        }
    }

    public static Number division(Number num1, Number num2) {
        if (num1 instanceof Integer || num1 instanceof Double || num1 instanceof Float || num1 instanceof Long || num1 instanceof Short || num1 instanceof Byte) {
            return num1.doubleValue() / num2.doubleValue();
        } else if (num1 instanceof BigInteger) {
            return ((BigInteger) num1).divide(new BigInteger(num2.toString()));
        } else if (num1 instanceof BigDecimal) {
            return ((BigDecimal) num1).divide(new BigDecimal(num2.toString()));
        } else {
            throw new IllegalArgumentException("Unsupported Number type");
        }
    }

    public static boolean hasRest(List<CljFuncParam> lst) {
        for (CljFuncParam m : lst)
        {
            if (m.getRestParam() != null)
            {
                return true;
            }
        }
        return false;
    }

    public List<CljFuncParamList> toFuncParamList(List<CljCell> lst) throws Exception {
        List<CljFuncParamList> rs = new ArrayList<>();
        for (int i = 0; i < lst.size(); i++)
        {
            CljCell c = lst.get(i);
            if (c.getCljCellType() == CljCellType.symbol) {
                rs.add(new CljFuncParamList(c.getCell().toString()));
            } else if (c.getCljCellType() == CljCellType.and_clj) {
                if (i == lst.size() - 2) {
                    CljFuncParamList cljFuncParam = new CljFuncParamList();
                    cljFuncParam.setName(lst.get(1 + i).getCell().toString());
                    rs.add(cljFuncParam);
                    break;
                }
            } else {
                throw new Exception("函数参数错误：" + lst.get(i).toString());
            }
        }
        if (rs.size() == 2) {
            return rs;
        }
        throw new Exception("函数参数错误：在函数参数中解析 [] 的格式通常是 [frist & rest]");
    }

    /**
     * 解析函数几种输入参数
     * 1、[a b c]
     * 2、[a b & c]
     * 3、[a b [c & d]]
     * */
    public List<CljFuncParam> toFuncParam(List<CljCell> lst) throws Exception {
        List<CljFuncParam> rs = new ArrayList<>();
        for (int i = 0; i < lst.size(); i++)
        {
            CljCell c = lst.get(i);
            if (c.getCljCellType() == CljCellType.symbol) {
                rs.add(new CljFuncParam(c.getCell().toString()));
            } else if (c.getCljCellType() == CljCellType.and_clj) {
                if (i == lst.size() - 2) {
                    CljFuncParam cljFuncParam = new CljFuncParam();
                    cljFuncParam.setRestParam(lst.get(1 + i).getCell().toString());
                    rs.add(cljFuncParam);
                    break;
                }
            } else if (c.getCljCellType() == CljCellType.bracket) {
                List<CljFuncParamList> cljFuncParamLists = toFuncParamList((ArrayList<CljCell>) c.getCell());
                CljFuncParam cljFuncParam = new CljFuncParam();
                cljFuncParam.setCljFuncParamList(cljFuncParamLists);
                rs.add(cljFuncParam);
            }
            else {
                throw new Exception("函数参数错误：" + lst.get(i).toString());
            }
        }
        return rs;
    }

    /**
     * function 中 funcOverride 添加 方法
     * */
    public static void addToFunc(MyCljFunc myCljFunc, CljFunc func) throws Exception {
        if (myCljFunc.getFuncOverride().containsKey(func.getFuncParams().size())) {
            throw new Exception("unexpected 相同的参数数量不能重载！");
        } else {
            for (Integer key : myCljFunc.getFuncOverride().keySet()) {
                CljFunc func1 = myCljFunc.getFuncOverride().get(key);
                if (hasRest(func1.getFuncParams()) && func1.getFuncParams().size() <= func.getFuncParams().size()) {
                    throw new Exception("unexpected 重载中的可变参数函数，中的参数数量不可以小于或等于其它函数的参数数量！");
                } else if (hasRest(func1.getFuncParams()) && hasRest(func.getFuncParams())) {
                    throw new Exception("unexpected 重载函数不可以有多个可变参数的函数");
                }
            }
            myCljFunc.getFuncOverride().put(func.getFuncParams().size(), func);
        }
    }

    /**
     * 让形参对应实参，返回 Hashtable
     * */
    public static Hashtable<String, CljCell> getParams(List<CljFuncParam> cljFuncParamList, List<CljCell> ps) {
        if (cljFuncParamList != null && cljFuncParamList.isEmpty() == false && ps != null && ps.isEmpty() == false)
        {
            Hashtable<String, CljCell> ht = new Hashtable<String, CljCell>();
            for (int i = 0; i < cljFuncParamList.size(); i++) {
                CljFuncParam m = cljFuncParamList.get(i);
                if (m.getName() != null) {
                    ht.put(m.getName(), ps.get(i));
                } else if (m.getRestParam() != null) {
                    ht.put(m.getRestParam(), new CljCell(CljCellType.list, ps.subList(i, ps.size())));
                } else if (m.getCljFuncParamList() != null && m.getCljFuncParamList().size() == 2) {
                    CljCell cell = ps.get(i);
                    if (cell.getCljCellType() == CljCellType.list || cell.getCljCellType() == CljCellType.bracket) {
                        List<CljCell> pss = (List<CljCell>) cell.getCell();
                        if (pss != null && pss.isEmpty() == false) {
                            ht.put(m.getCljFuncParamList().get(0).getName(), pss.get(0));
                            ht.put(m.getCljFuncParamList().get(1).getName(), new CljCell(CljCellType.list, pss.subList(1, pss.size())));
                        }
                    }
                }
            }
            return ht;
        }
        return null;
    }

    public CljFunc to_param_body(String fname, List<CljCell> param_body) throws Exception {
        CljCell fb = param_body.get(0);
        // 如果是 [a b] 这种类型
        if (fb.getCljCellType() == CljCellType.bracket) {
            // 函数参数
            List<CljFuncParam> funcParams = toFuncParam((List<CljCell>) fb.getCell());

            List<CljCell> lst_body = param_body.subList(1, param_body.size());
            if (lst_body != null && lst_body.size() > 0)
            {
                // 将函数存储到 funcs 列表
                //this.funcs.put(fname, new MyCljFunc(new CljFunc(funcParams, lst_body.get(0))));
                return new CljFunc(funcParams, lst_body.get(0));
            }
        }
        throw new Exception("unexpected " + fname + " 输入参数的格式错误！");
    }

    /**
     * 执行 (defn) 里面的内容
     * */
    public void Clj_list_defn(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        CljCell f = lst.get(1);

        if (f != null) {
            // 函数名
            String fname = f.getCell().toString();

            List<CljCell> cellList = lst.subList(2, lst.size());

            if (cellList.size() == 2 && cellList.get(0).getCljCellType() == CljCellType.bracket && cellList.get(1).getCljCellType() == CljCellType.Clj_list)
            {
                CljFunc func = to_param_body(fname, cellList);
                this.funcs.put(fname, new MyCljFunc(func));
            }
            else
            {
                MyCljFunc myCljFunc = new MyCljFunc(true);
                for (CljCell c1: cellList)
                {
                    if (c1.getCljCellType() == CljCellType.Clj_list)
                    {
                        CljFunc func = to_param_body(fname, (List<CljCell>) c1.getCell());
                        addToFunc(myCljFunc, func);
                        //myCljFunc.getFuncOverride().put(func.getFuncParams().size(), func);
                    }
                }
                this.funcs.put(fname, myCljFunc);
            }
        }
    }

    public void Clj_list_symbol(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        CljCell c = lst.get(0);
        // 判断是否存在 func 中
        if (this.funcs.containsKey(c.getCell().toString())) {
            MyCljFunc myCljFunc = this.funcs.get(c.getCell().toString());
            // 判断是否是 override
            if (myCljFunc.getOverride()) {
                Integer psNum = lst.size() - 1;
                CljFunc cljFunc = myCljFunc.getCljFunc(psNum);
                if (cljFunc != null) {

                    // 参数
                    List<CljFuncParam> cljFuncParamList = cljFunc.getFuncParams();
                    // 函数体
                    CljCell cljCellBody = cljFunc.getFuncBody();
                    Hashtable<String, CljCell> ht = getParams(cljFuncParamList, lst.subList(1, lst.size()));
                    cljRecur = new CljRecur();
                    cljRecur.setFuncCellBody(cljCellBody);
                    cljRecur.setCljFuncParamList(cljFuncParamList);
                    eval(cljCellBody, ht, cljRecur, rs);
                }
            } else {
                CljFunc cljFunc = myCljFunc.getCljFunc();
                // 参数
                List<CljFuncParam> cljFuncParamList = cljFunc.getFuncParams();
                // 函数体
                CljCell cljCellBody = cljFunc.getFuncBody();
                Hashtable<String, CljCell> ht = getParams(cljFuncParamList, lst.subList(1, lst.size()));
                cljRecur = new CljRecur();
                cljRecur.setFuncCellBody(cljCellBody);
                cljRecur.setCljFuncParamList(cljFuncParamList);
                eval(cljCellBody, ht, cljRecur, rs);
            }
        } else if (funcHs != null && funcHs.containsKey(c.getCell().toString())) {
            rs = funcHs.get(c.getCell().toString());
        } else {
            throw new Exception("unexpected 未定义字符 " + c.getCell().toString());
        }
    }

    public void Clj_list_func_recur(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {


        CljCell c = lst.get(0);
        // 判断是否存在 func 中
        if (this.funcs.containsKey(c.getCell().toString())) {
            MyCljFunc myCljFunc = this.funcs.get(c.getCell().toString());
            // 判断是否是 override
            if (myCljFunc.getOverride()) {
                Integer psNum = lst.size() - 1;
                CljFunc cljFunc = myCljFunc.getCljFunc(psNum);
                if (cljFunc != null) {

                    // 参数
                    List<CljFuncParam> cljFuncParamList = cljFunc.getFuncParams();
                    // 函数体
                    CljCell cljCellBody = cljFunc.getFuncBody();
                    Hashtable<String, CljCell> ht = getParams(cljFuncParamList, lst.subList(1, lst.size()));
                    eval(cljCellBody, ht, cljRecur, rs);
                }
            } else {
                CljFunc cljFunc = myCljFunc.getCljFunc();
                // 参数
                List<CljFuncParam> cljFuncParamList = cljFunc.getFuncParams();
                // 函数体
                CljCell cljCellBody = cljFunc.getFuncBody();
                Hashtable<String, CljCell> ht = getParams(cljFuncParamList, lst.subList(1, lst.size()));
                eval(cljCellBody, ht, cljRecur, rs);
            }
        }
    }

    /**
     * 加法
     * */
    public void Clj_list_addition(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        // + 加法
        Number number = 0;
        for (CljCell addCell: lst.subList(1, lst.size()))
        {
            if (addCell.getCljCellType() == CljCellType.number_clj) {
                number = add(number, (Number)addCell.getCell());
            } else if (addCell.getCljCellType() == CljCellType.symbol) {
                CljCell addps = funcHs.get(addCell.getCell().toString());
                if (addps.getCljCellType() == CljCellType.number_clj) {
                    number = add(number, (Number)addps.getCell());
                } else if (addps.getCljCellType() == CljCellType.Clj_list) {
                    eval((CljCell)addps.getCell(), funcHs, cljRecur, rs);
                    if (rs.getCljCellType() == CljCellType.number_clj) {
                        number = add(number, (Number)rs.getCell());
                    } else {
                        throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
                    }
                }
                else {
                    throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
                }
            }
            else {
                eval(addCell, funcHs, cljRecur, rs);
                if (rs.getCljCellType() == CljCellType.number_clj) {
                    number = add(number, (Number)rs.getCell());
                } else {
                    throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
                }
            }
        }
        rs.setCljCellType(CljCellType.number_clj);
        rs.setCell(number);
    }

    /**
     * 减法
     * */
    public void Clj_list_subtraction(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        // - 减法
        //CljList sublst = toClj(lst.subList(1, lst.size()));
        List<CljCell> sublst = lst.subList(1, lst.size());
        CljCell subfirst = sublst.get(0);
        Number number3 = 0;
        if (subfirst.getCljCellType() == CljCellType.number_clj)
        {
            number3 = (Number)subfirst.getCell();
        }
        else if (subfirst.getCljCellType() == CljCellType.symbol)
        {
            CljCell subps = funcHs.get(subfirst.getCell().toString());
            if (subps.getCljCellType() == CljCellType.number_clj) {
                number3 = (Number)subps.getCell();
            } else if (subps.getCljCellType() == CljCellType.Clj_list) {
                eval((CljCell)subps.getCell(), funcHs, cljRecur, rs);
                if (rs.getCljCellType() == CljCellType.number_clj) {
                    number3 = (Number)rs.getCell();
                } else {
                    throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
                }
            }
            else {
                throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
            }
        }
        else {
            throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
        }

        for (CljCell subCell1: sublst.subList(1, sublst.size()))
        {
            if (subCell1.getCljCellType() == CljCellType.number_clj) {
                number3 = subtraction(number3, (Number)subCell1.getCell());
            } else if (subCell1.getCljCellType() == CljCellType.symbol) {
                CljCell subps1 = funcHs.get(subCell1.getCell().toString());
                if (subps1.getCljCellType() == CljCellType.number_clj) {
                    number3 = subtraction(number3, (Number)subps1.getCell());
                } else if (subps1.getCljCellType() == CljCellType.Clj_list) {
                    eval((CljCell)subps1.getCell(), funcHs, cljRecur, rs);
                    if (rs.getCljCellType() == CljCellType.number_clj) {
                        number3 = subtraction(number3, (Number)rs.getCell());
                    } else {
                        throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
                    }
                }
                else {
                    throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
                }
            }
            else {
                eval(subCell1, funcHs, cljRecur, rs);
                if (rs.getCljCellType() == CljCellType.number_clj) {
                    number3 = subtraction(number3, (Number)rs.getCell());
                } else {
                    throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
                }
            }
        }
        rs.setCljCellType(CljCellType.number_clj);
        rs.setCell(number3);
    }

    /**
     * * 乘法
     * */
    public void Clj_list_multiplication(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        // * 乘法
        Number number2 = 1;
        for (CljCell multCell2: lst.subList(1, lst.size()))
        {
            if (multCell2.getCljCellType() == CljCellType.number_clj) {
                number2 = multiplication(number2, (Number)multCell2.getCell());
            } else if (multCell2.getCljCellType() == CljCellType.symbol) {
                CljCell multps2 = funcHs.get(multCell2.getCell().toString());
                if (multps2.getCljCellType() == CljCellType.number_clj) {
                    number2 = multiplication(number2, (Number)multps2.getCell());
                } else if (multps2.getCljCellType() == CljCellType.Clj_list) {
                    eval((CljCell)multps2.getCell(), funcHs, cljRecur, rs);
                    if (rs.getCljCellType() == CljCellType.number_clj) {
                        number2 = multiplication(number2, (Number)rs.getCell());
                    } else {
                        throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
                    }
                }
                else {
                    throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
                }
            }
            else {
                eval(multCell2, funcHs, cljRecur, rs);
                if (rs.getCljCellType() == CljCellType.number_clj) {
                    number2 = multiplication(number2, (Number)rs.getCell());
                } else {
                    throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
                }
            }
        }
        rs.setCljCellType(CljCellType.number_clj);
        rs.setCell(number2);
    }

    /**
     * / 除法
     * */
    public void Clj_list_division(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        // / 除法
        Number number4 = 0;
        //CljList divlst = toClj(lst.subList(1, lst.size()));
        List<CljCell> divlst = lst.subList(1, lst.size());
        CljCell divfirst = divlst.get(0);
        if (divfirst.getCljCellType() == CljCellType.number_clj)
        {
            number4 = (Number)divfirst.getCell();
        }
        else if (divfirst.getCljCellType() == CljCellType.symbol)
        {
            CljCell divps = funcHs.get(divfirst.getCell().toString());
            if (divps.getCljCellType() == CljCellType.number_clj) {
                number4 = (Number)divps.getCell();
            } else if (divps.getCljCellType() == CljCellType.Clj_list) {
                eval((CljCell)divps.getCell(), funcHs, cljRecur, rs);
                if (rs.getCljCellType() == CljCellType.number_clj) {
                    number4 = (Number)rs.getCell();
                } else {
                    throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
                }
            }
            else {
                throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
            }
        }
        else {
            throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
        }

        for (CljCell divCell1: divlst.subList(1, divlst.size()))
        {
            if (divCell1.getCljCellType() == CljCellType.number_clj) {
                number4 = division(number4, (Number)divCell1.getCell());
            } else if (divCell1.getCljCellType() == CljCellType.symbol) {
                CljCell divps1 = funcHs.get(divCell1.getCell().toString());
                if (divps1.getCljCellType() == CljCellType.number_clj) {
                    number4 = division(number4, (Number)divps1.getCell());
                } else if (divps1.getCljCellType() == CljCellType.Clj_list) {
                    eval((CljCell)divps1.getCell(), funcHs, cljRecur, rs);
                    if (rs.getCljCellType() == CljCellType.number_clj) {
                        number4 = division(number4, (Number)rs.getCell());
                    } else {
                        throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
                    }
                }
                else {
                    throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
                }
            }
            else {
                eval(divCell1, funcHs, cljRecur, rs);
                if (rs.getCljCellType() == CljCellType.number_clj) {
                    number4 = division(number4, (Number)rs.getCell());
                } else {
                    throw new Exception("unexpected " + rs.toString() + " 数据类型不能做加法运算！");
                }
            }
        }
        rs.setCljCellType(CljCellType.number_clj);
        rs.setCell(number4);
    }

    /**
     * apply 计算
     * */
    public void Clj_list_apply(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        // apply 计算
        List<CljCell> applyLst = lst.subList(1, lst.size());

        List<CljCell> applyLstNew = new ArrayList<>();
        applyLstNew.add(applyLst.get(0));

        CljCell appCell = new CljCell();
        appCell.setCljCellType(CljCellType.Clj_list);

        if (applyLst.get(1).getCljCellType() == CljCellType.list || applyLst.get(1).getCljCellType() == CljCellType.bracket) {
            for (CljCell cljCell : (List<CljCell>)applyLst.get(1).getCell()) {
                applyLstNew.add(cljCell);
            }
        } else if (applyLst.get(1).getCljCellType() == CljCellType.symbol) {
            CljCell ps = funcHs.get(applyLst.get(1).getCell().toString());
            if (ps.getCljCellType() == CljCellType.list || ps.getCljCellType() == CljCellType.set || ps.getCljCellType() == CljCellType.bracket) {
                for (CljCell cljResult : (List<CljCell>)ps.getCell()) {
                    applyLstNew.add(cljResult);
                }
            } else if (ps.getCljCellType() == CljCellType.hash_table) {

            }
        } else if (applyLst.get(1).getCljCellType() == CljCellType.braces) {

        }
        appCell.setCell(applyLstNew);
        eval(appCell, funcHs, cljRecur, rs);
    }

    /**
     * cond 计算
     * */
    public void Clj_list_cond(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        // cond 计算
        if (lst.size() > 1 && lst.size() % 2 > 0) {
            for (int i = 1; i < lst.size(); i += 2) {
                if (lst.size() > i + 1) {
                    CljCell c = lst.get(i);
                    if (c.getCljCellType() == CljCellType.Clj_list) {
                        eval(c, funcHs, cljRecur, rs);
                        if (rs.getCljCellType() == CljCellType.boolean_clj && (boolean)rs.getCell())
                        {
                            eval(lst.get(i + 1), funcHs, cljRecur, rs);
                            break;
                        }
                    } else if (c.getCljCellType() == CljCellType.boolean_clj){
                        eval(lst.get(i + 1), funcHs, cljRecur, rs);
                        break;
                    } else if (c.getCljCellType() == CljCellType.else_clj) {
                        eval(lst.get(i + 1), funcHs, cljRecur, rs);
                        break;
                    } else {
                        throw new Exception("unexpected (cond " + lst.get(i).toString() + ") 这里面的数据必须成对！");
                    }
                }
                else {
                    throw new Exception("unexpected (cond " + lst.get(i).toString() + ") 这里面的数据必须成对！");
                }
            }
        }
    }

    /**
     * if 计算
     * */
    public void Clj_list_if(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        // if 计算
        if (lst.size() == 3) {
            CljCell c = lst.get(1);
            if (c.getCljCellType() == CljCellType.Clj_list) {
                eval(c, funcHs, cljRecur, rs);
                if (rs.getCljCellType() == CljCellType.boolean_clj && (boolean)rs.getCell())
                {
                    eval(lst.get(2), funcHs, cljRecur, rs);
                }
            } else if (c.getCljCellType() == CljCellType.boolean_clj && (boolean)c.getCell()){
                eval(lst.get(2), funcHs, cljRecur, rs);
            }
        } else if (lst.size() == 4) {
            CljCell c = lst.get(1);
            if (c.getCljCellType() == CljCellType.Clj_list) {
                eval(c, funcHs, cljRecur, rs);
                if (rs.getCljCellType() == CljCellType.boolean_clj && (boolean)rs.getCell())
                {
                    eval(lst.get(2), funcHs, cljRecur, rs);
                } else {
                    eval(lst.get(3), funcHs, cljRecur, rs);
                }
            } else if (c.getCljCellType() == CljCellType.boolean_clj){
                if ((boolean)c.getCell()) {
                    eval(lst.get(2), funcHs, cljRecur, rs);
                } else {
                    eval(lst.get(3), funcHs, cljRecur, rs);
                }
            }
        }
        rs.setCljCellType(CljCellType.nil);
        rs.setCell(null);
    }

    /**
     * do 计算
     * */
    public void Clj_list_do(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        // cond 计算
        if (lst.size() > 1) {
            for (int i = 1; i < lst.size(); i++) {
                eval(lst.get(i), funcHs, cljRecur, rs);
            }
        }
    }

    /**
     * and
     * */
    public void Clj_list_and(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        /**
         * (and () ())
         * */
        boolean myrs = true;
        if (lst.size() > 1) {
            for (int i = 1; i < lst.size(); i++) {
                CljCell c = lst.get(i);
                if (c.getCljCellType() == CljCellType.boolean_clj && (boolean)c.getCell() == false) {
                    rs.setCljCellType(CljCellType.boolean_clj);
                    rs.setCell(false);
                    break;
                }
                else if (c.getCljCellType() == CljCellType.Clj_list) {
                    eval((CljCell) c.getCell(), funcHs, cljRecur, rs);

                    if (rs.getCljCellType() == CljCellType.boolean_clj && (boolean)c.getCell() == false)
                    {
                        rs.setCljCellType(CljCellType.boolean_clj);
                        rs.setCell(false);
                        break;
                    }
                    else {
                        throw new Exception("unexpected " + c.getCell().toString() + "的结果是非 boolean 类型！");
                    }
                }
            }
        }
        rs.setCljCellType(CljCellType.boolean_clj);
        rs.setCell(myrs);
    }

    /**
     * or
     * */
    public void Clj_list_or(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        /**
         * (or () ())
         * */
        boolean myrs = false;
        if (lst.size() > 1) {
            for (int i = 1; i < lst.size(); i++) {
                CljCell c = lst.get(i);
                if (c.getCljCellType() == CljCellType.boolean_clj && (boolean) c.getCell() == true) {
                    myrs = true;
                    break;
                } else if (c.getCljCellType() == CljCellType.Clj_list) {
                    eval((CljCell) c.getCell(), funcHs, cljRecur, rs);

                    if (rs.getCljCellType() == CljCellType.boolean_clj && (boolean) c.getCell() == true) {
                        myrs = true;
                        break;
                    } else {
                        throw new Exception("unexpected " + c.getCell().toString() + "的结果是非 boolean 类型！");
                    }
                }
            }
        }
        rs.setCljCellType(CljCellType.boolean_clj);
        rs.setCell(myrs);
    }

    /**
     * 等于
     * */
    public void Clj_list_equals(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        boolean myrs = true;
        if (lst.size() > 1) {
            CljCell tmp = lst.get(1);
            for (int i = 2; i < lst.size(); i++) {
                CljCell c = lst.get(i);
                if (c.getCljCellType() == CljCellType.number_clj && !c.getCell().equals(tmp.getCell())) {
                    myrs = false;
                    break;
                } else if (c.getCljCellType() == CljCellType.Clj_list) {
                    eval((CljCell) c.getCell(), funcHs, cljRecur, rs);

                    if (rs.getCljCellType() == CljCellType.boolean_clj && !c.getCell().equals(tmp.getCell())) {
                        myrs = false;
                        break;
                    } else {
                        throw new Exception("unexpected " + c.getCell().toString() + "的结果是非 boolean 类型！");
                    }
                }
            }
        }
        rs.setCljCellType(CljCellType.boolean_clj);
        rs.setCell(myrs);
    }

    /**
     * 大于 只有数值类型、日期类型才能比大小
     * */
    public void Clj_list_greater_than(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        boolean myrs = true;
        if (lst.size() > 1) {
            CljCell tmp = lst.get(1);
            for (int i = 2; i < lst.size(); i++) {
                CljCell c = lst.get(i);
                // c 数值类型
                if (c.getCljCellType() == CljCellType.number_clj) {
                    if (tmp.getCljCellType() == CljCellType.number_clj) {
                        Number n1 = (Number)tmp.getCell();
                        Number n2 = (Number)c.getCell();
                        if (n1.doubleValue() <= n2.doubleValue()) {
                            myrs = false;
                            break;
                        }
                        tmp = lst.get(i);
                    } else if (tmp.getCljCellType() == CljCellType.symbol && funcHs != null) {
                        CljCell cljCell = funcHs.get(tmp.getCell().toString());
                        if (cljCell != null && cljCell.getCljCellType() == CljCellType.number_clj) {
                            Number n1 = (Number)cljCell.getCell();
                            Number n2 = (Number)c.getCell();
                            if (n1.doubleValue() <= n2.doubleValue()) {
                                myrs = false;
                                break;
                            }
                            tmp = lst.get(i);
                        } else {
                            throw new Exception("unexpected " + tmp.getCell().toString() + " 非数值类型不能比较！");
                        }
                    } else if (tmp.getCljCellType() == CljCellType.Clj_list)  {
                        eval(tmp, funcHs, cljRecur, rs);
                        if (rs != null && rs.getCljCellType() == CljCellType.number_clj) {
                            Number n1 = (Number) rs.getCell();
                            Number n2 = (Number) c.getCell();
                            if (n1.doubleValue() <= n2.doubleValue()) {
                                myrs = false;
                                break;
                            }
                            tmp = lst.get(i);
                        }
                    } else {
                        throw new Exception("unexpected " + tmp.getCell().toString() + " 非数值类型不能比较！");
                    }
                }
                // date 类型
                else if (c.getCljCellType() == CljCellType.date_clj) {
                    if (tmp.getCljCellType() == CljCellType.date_clj) {
                        Date n1 = (Date)tmp.getCell();
                        Date n2 = (Date)c.getCell();
                        int comparison = n1.compareTo(n2);
                        if (comparison <= 0) {
                            myrs = false;
                            break;
                        }
                        tmp = lst.get(i);
                    } else if (tmp.getCljCellType() == CljCellType.symbol && funcHs != null) {
                        CljCell cljCell = funcHs.get(tmp.getCell().toString());
                        if (cljCell != null && cljCell.getCljCellType() == CljCellType.date_clj) {
                            Date n1 = (Date)cljCell.getCell();
                            Date n2 = (Date)c.getCell();
                            int comparison1 = n1.compareTo(n2);
                            if (comparison1 <= 0) {
                                myrs = false;
                                break;
                            }
                            tmp = lst.get(i);
                        }  else {
                            throw new Exception("unexpected " + tmp.getCell().toString() + " 非数值类型不能比较！");
                        }
                    } else if (tmp.getCljCellType() == CljCellType.Clj_list) {
                        eval(tmp, funcHs, cljRecur, rs);
                        if (rs != null && rs.getCljCellType() == CljCellType.date_clj) {
                            Date n1 = (Date) rs.getCell();
                            Date n2 = (Date) c.getCell();
                            int comparison2 = n1.compareTo(n2);
                            if (comparison2 <= 0) {
                                myrs = false;
                                break;
                            }
                            tmp = lst.get(i);
                        }
                    } else {
                        throw new Exception("unexpected " + tmp.getCell().toString() + " 非数值类型不能比较！");
                    }
                }
                // Clj_list 类型
                else if (c.getCljCellType() == CljCellType.Clj_list) {
                    eval(c, funcHs, cljRecur, rs);
                    if (tmp.getCljCellType() == CljCellType.number_clj && rs.getCljCellType() == CljCellType.number_clj) {
                        Number n1 = (Number)tmp.getCell();
                        Number n2 = (Number)rs.getCell();
                        if (n1.doubleValue() <= n2.doubleValue()) {
                            myrs = false;
                            break;
                        }
                        tmp = lst.get(i);
                    } else if (tmp.getCljCellType() == CljCellType.date_clj && rs.getCljCellType() == CljCellType.date_clj) {
                        Date n1 = (Date)tmp.getCell();
                        Date n2 = (Date)rs.getCell();
                        int comparison = n1.compareTo(n2);
                        if (comparison <= 0) {
                            myrs = false;
                            break;
                        }
                        tmp = lst.get(i);
                    } else if (tmp.getCljCellType() == CljCellType.symbol && funcHs != null) {
                        CljCell cljCell = funcHs.get(tmp.getCell().toString());
                        if (cljCell != null && cljCell.getCljCellType() == CljCellType.date_clj && rs.getCljCellType() == CljCellType.date_clj) {
                            Date n1 = (Date)cljCell.getCell();
                            Date n2 = (Date)rs.getCell();
                            int comparison1 = n1.compareTo(n2);
                            if (comparison1 <= 0) {
                                myrs = false;
                                break;
                            }
                            tmp = lst.get(i);
                        } else if (cljCell != null && cljCell.getCljCellType() == CljCellType.number_clj && rs.getCljCellType() == CljCellType.number_clj) {
                            Number n1 = (Number)tmp.getCell();
                            Number n2 = (Number)rs.getCell();
                            if (n1.doubleValue() <= n2.doubleValue()) {
                                myrs = false;
                                break;
                            }
                            tmp = lst.get(i);
                        } else {
                            throw new Exception("unexpected " + c.getCell().toString() + " 非数值类型或者日期类型不能比较！");
                        }
                    }
                }
            }
            rs.setCljCellType(CljCellType.boolean_clj);
            rs.setCell(myrs);
        }
    }

    /**
     * 小于
     * */
    public void Clj_list_less_than(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        boolean myrs = true;
        if (lst.size() > 1) {
            CljCell tmp = lst.get(1);
            for (int i = 2; i < lst.size(); i++) {
                CljCell c = lst.get(i);
                // c 数值类型
                if (c.getCljCellType() == CljCellType.number_clj) {
                    if (tmp.getCljCellType() == CljCellType.number_clj) {
                        Number n1 = (Number)tmp.getCell();
                        Number n2 = (Number)c.getCell();
                        if (n1.doubleValue() >= n2.doubleValue()) {
                            myrs = false;
                            break;
                        }
                        tmp = lst.get(i);
                    } else if (tmp.getCljCellType() == CljCellType.symbol && funcHs != null) {
                        CljCell cljCell = funcHs.get(tmp.getCell().toString());
                        if (cljCell != null && cljCell.getCljCellType() == CljCellType.number_clj) {
                            Number n1 = (Number)cljCell.getCell();
                            Number n2 = (Number)c.getCell();
                            if (n1.doubleValue() >= n2.doubleValue()) {
                                myrs = false;
                                break;
                            }
                            tmp = lst.get(i);
                        } else {
                            throw new Exception("unexpected " + tmp.getCell().toString() + " 非数值类型不能比较！");
                        }
                    } else if (tmp.getCljCellType() == CljCellType.Clj_list)  {
                        eval(tmp, funcHs, cljRecur, rs);
                        if (rs != null && rs.getCljCellType() == CljCellType.number_clj) {
                            Number n1 = (Number) rs.getCell();
                            Number n2 = (Number) c.getCell();
                            if (n1.doubleValue() >= n2.doubleValue()) {
                                myrs = false;
                                break;
                            }
                            tmp = lst.get(i);
                        }
                    } else {
                        throw new Exception("unexpected " + tmp.getCell().toString() + " 非数值类型不能比较！");
                    }
                }
                // date 类型
                else if (c.getCljCellType() == CljCellType.date_clj) {
                    if (tmp.getCljCellType() == CljCellType.date_clj) {
                        Date n1 = (Date)tmp.getCell();
                        Date n2 = (Date)c.getCell();
                        int comparison = n1.compareTo(n2);
                        if (comparison >= 0) {
                            myrs = false;
                            break;
                        }
                        tmp = lst.get(i);
                    } else if (tmp.getCljCellType() == CljCellType.symbol && funcHs != null) {
                        CljCell cljCell = funcHs.get(tmp.getCell().toString());
                        if (cljCell != null && cljCell.getCljCellType() == CljCellType.date_clj) {
                            Date n1 = (Date)cljCell.getCell();
                            Date n2 = (Date)c.getCell();
                            int comparison1 = n1.compareTo(n2);
                            if (comparison1 >= 0) {
                                myrs = false;
                                break;
                            }
                            tmp = lst.get(i);
                        }  else {
                            throw new Exception("unexpected " + tmp.getCell().toString() + " 非数值类型不能比较！");
                        }
                    } else if (tmp.getCljCellType() == CljCellType.Clj_list) {
                        eval(tmp, funcHs, cljRecur, rs);
                        if (rs != null && rs.getCljCellType() == CljCellType.date_clj) {
                            Date n1 = (Date) rs.getCell();
                            Date n2 = (Date) c.getCell();
                            int comparison2 = n1.compareTo(n2);
                            if (comparison2 >= 0) {
                                myrs = false;
                                break;
                            }
                            tmp = lst.get(i);
                        }
                    } else {
                        throw new Exception("unexpected " + tmp.getCell().toString() + " 非数值类型不能比较！");
                    }
                }
                // Clj_list 类型
                else if (c.getCljCellType() == CljCellType.Clj_list) {
                    eval(c, funcHs, cljRecur, rs);
                    if (tmp.getCljCellType() == CljCellType.number_clj && rs.getCljCellType() == CljCellType.number_clj) {
                        Number n1 = (Number)tmp.getCell();
                        Number n2 = (Number)rs.getCell();
                        if (n1.doubleValue() >= n2.doubleValue()) {
                            myrs = false;
                            break;
                        }
                        tmp = lst.get(i);
                    } else if (tmp.getCljCellType() == CljCellType.date_clj && rs.getCljCellType() == CljCellType.date_clj) {
                        Date n1 = (Date)tmp.getCell();
                        Date n2 = (Date)rs.getCell();
                        int comparison = n1.compareTo(n2);
                        if (comparison >= 0) {
                            myrs = false;
                            break;
                        }
                        tmp = lst.get(i);
                    } else if (tmp.getCljCellType() == CljCellType.symbol && funcHs != null) {
                        CljCell cljCell = funcHs.get(tmp.getCell().toString());
                        if (cljCell != null && cljCell.getCljCellType() == CljCellType.date_clj && rs.getCljCellType() == CljCellType.date_clj) {
                            Date n1 = (Date)cljCell.getCell();
                            Date n2 = (Date)rs.getCell();
                            int comparison1 = n1.compareTo(n2);
                            if (comparison1 >= 0) {
                                myrs = false;
                                break;
                            }
                            tmp = lst.get(i);
                        } else if (cljCell != null && cljCell.getCljCellType() == CljCellType.number_clj && rs.getCljCellType() == CljCellType.number_clj) {
                            Number n1 = (Number)tmp.getCell();
                            Number n2 = (Number)rs.getCell();
                            if (n1.doubleValue() >= n2.doubleValue()) {
                                myrs = false;
                                break;
                            }
                            tmp = lst.get(i);
                        } else {
                            throw new Exception("unexpected " + c.getCell().toString() + " 非数值类型或者日期类型不能比较！");
                        }
                    }
                }
            }
            rs.setCljCellType(CljCellType.boolean_clj);
            rs.setCell(myrs);
        }
    }

    /**
     * 大于等于
     * */
    public void Clj_list_greater_equals(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        boolean myrs = true;
        if (lst.size() > 1) {
            CljCell tmp = lst.get(1);
            for (int i = 2; i < lst.size(); i++) {
                CljCell c = lst.get(i);
                if (c.getCljCellType() == CljCellType.number_clj) {
                    Number n1 = (Number)tmp.getCell();
                    Number n2 = (Number)c.getCell();
                    if (n1.doubleValue() < n2.doubleValue()) {
                        myrs = false;
                        break;
                    }
                    tmp = lst.get(i);
                } else if (c.getCljCellType() == CljCellType.Clj_list) {
                    eval((CljCell) c.getCell(), funcHs, cljRecur, rs);

                    if (rs.getCljCellType() == CljCellType.boolean_clj) {
                        Number n1 = (Number)tmp.getCell();
                        Number n2 = (Number)c.getCell();
                        if (n1.doubleValue() < n2.doubleValue()) {
                            myrs = false;
                            break;
                        }
                        tmp = lst.get(i);
                    } else {
                        throw new Exception("unexpected " + c.getCell().toString() + "的结果是非 boolean 类型！");
                    }
                }
            }
        }
        rs.setCljCellType(CljCellType.boolean_clj);
        rs.setCell(myrs);
    }

    /**
     * 小于等于
     * */
    public void Clj_list_less_equals(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        boolean myrs = true;
        if (lst.size() > 1) {
            CljCell tmp = lst.get(1);
            for (int i = 2; i < lst.size(); i++) {
                CljCell c = lst.get(i);
                if (c.getCljCellType() == CljCellType.number_clj) {
                    Number n1 = (Number)tmp.getCell();
                    Number n2 = (Number)c.getCell();
                    if (n1.doubleValue() > n2.doubleValue()) {
                        myrs = false;
                        break;
                    }
                    tmp = lst.get(i);
                } else if (c.getCljCellType() == CljCellType.Clj_list) {
                    eval((CljCell) c.getCell(), funcHs, cljRecur, rs);

                    if (rs.getCljCellType() == CljCellType.boolean_clj) {
                        Number n1 = (Number)tmp.getCell();
                        Number n2 = (Number)c.getCell();
                        if (n1.doubleValue() > n2.doubleValue()) {
                            myrs = false;
                            break;
                        }
                        tmp = lst.get(i);
                    } else {
                        throw new Exception("unexpected " + c.getCell().toString() + "的结果是非 boolean 类型！");
                    }
                }
            }
        }
        rs.setCljCellType(CljCellType.boolean_clj);
        rs.setCell(myrs);
    }

    /**
     * loop 语句
     * */
    public void Clj_list_loop(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        if (lst.size() >= 3) {
            CljCell bindings = lst.get(1);
            if (bindings.getCljCellType() == CljCellType.bracket) {
                CljRecur cljRecur1 = new CljRecur(new Hashtable<Integer, String>());
                List<CljCell> pss = (List<CljCell>) bindings.getCell();
                int index = 1;
                for (int i = 0; i < pss.size(); i += 2) {
                    CljCell c1 = pss.get(i);
                    CljCell c2 = pss.get(i + 1);
                    if (c1.getCljCellType() == CljCellType.symbol) {
                        eval(c2, funcHs, cljRecur, rs);
                        funcHs.put(c1.getCell().toString(), new CljCell(rs.getCljCellType(), rs.getCell()));
                        cljRecur1.getHt().put(index, c1.getCell().toString());
                        index++;
                    }
                }

                for (int i = 2; i < lst.size(); i++) {
                    cljRecur1.setCljCell(lst.get(i));
                    eval(lst.get(i), funcHs, cljRecur1, rs);
                    //Clj_list_loop_inner(lst.get(i), funcHs, cljRecur1, rs);
                }
            }
        } else {
            throw new Exception("unexpected: let 的用法是：(let [bindings*] exprs*) 的！");
        }
    }

    public void Clj_list_recur(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        if (lst.size() > 1) {
            if (cljRecur.getFuncCellBody() != null) {
                List<CljCell> lstrs = new ArrayList<>();
                for (int i = 1; i < lst.size(); i++) {
                    CljCell cljCell = lst.get(1);
                    eval(cljCell, funcHs, cljRecur, rs);
                    lstrs.add(rs);
                }
                // 修改传入参数的值
                Hashtable<String, CljCell> ht = getParams(cljRecur.getCljFuncParamList(), lstrs);
                eval(cljRecur.getFuncCellBody(), ht, cljRecur, rs);
            } else {
                int index = 1;
                Hashtable<String, CljCell> subht = new Hashtable<String, CljCell>();
                for (int i = 1; i < lst.size(); i++) {
                    CljCell rs1 = eval(lst.get(i), funcHs, cljRecur, new CljCell());
                    String key = cljRecur.getHt().get(index);
                    //funcHs.replace(key, rs1);
                    subht.put(key, rs1);
                    index++;
                }
                for (String key : subht.keySet()) {
                    funcHs.replace(key, subht.get(key));
                }

                /**
                 * 2、在调用一次原来的代码
                 * */
                eval(cljRecur.getCljCell(), funcHs, cljRecur, rs);
            }
        }

//        /**
//         * 1、修改 funcHs 的内容
//         * */
//        if (lst.size() > 1) {
//            if (cljRecur.getFuncName() == null) {
//                int index = 1;
//                for (int i = 1; i < lst.size(); i++) {
//                    eval(lst.get(i), funcHs, cljRecur, rs);
//                    String key = cljRecur.getHt().get(index);
//                    funcHs.replace(key, rs);
//                    index++;
//                }
//
//                /**
//                 * 2、在调用一次原来的代码
//                 * */
//                eval(cljRecur.getCljCell(), funcHs, cljRecur, rs);
//            } else {
//                lst.set(0, new CljCell(CljCellType.symbol, cljRecur.getFuncName()));
//                eval(new CljCell(CljCellType.Clj_list, lst), funcHs, cljRecur, rs);
//            }
//        }
    }

    /**
     * let 语句
     * */
    public void Clj_list_let(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur, CljCell rs) throws Exception {
        if (lst.size() >= 3) {
            CljCell bindings = lst.get(1);
            if (bindings.getCljCellType() == CljCellType.bracket) {
                List<CljCell> pss = (List<CljCell>) bindings.getCell();
                for (int i = 0; i < pss.size(); i += 2) {
                    CljCell c1 = pss.get(i);
                    CljCell c2 = pss.get(i + 1);
                    if (c1.getCljCellType() == CljCellType.symbol) {
                        CljCell rs1 = eval(c2, funcHs, cljRecur, new CljCell());
                        funcHs.put(c1.getCell().toString(), rs1);
                    }
                }

                for (int i = 2; i < lst.size(); i++) {
                    rs = eval(lst.get(i), funcHs, cljRecur, new CljCell());
                }
            }
        } else {
            throw new Exception("unexpected: let 的用法是：(let [bindings*] exprs*) 的！");
        }
    }

    /**
     * not 语句
     * */
    public void Clj_list_not(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        if (lst.size() == 2) {
            CljCell c = lst.get(1);
            if (c.getCljCellType() == CljCellType.boolean_clj) {
                boolean b = (boolean)c.getCell();
                rs.setCell(!b);
            } else {
                CljCell rs1 = eval(c, funcHs, cljRecur, new CljCell());
                if (rs1.getCljCellType() == CljCellType.boolean_clj) {
                    boolean b = (boolean)rs1.getCell();
                    rs1.setCell(!b);
                    rs.setCell(rs1.getCell());
                } else {
                    throw new Exception("(not x) 如果 x 为逻辑 false，则返回 true，否则返回 false。");
                }
            }
        } else {
            throw new Exception("(not x) 如果 x 为逻辑 false，则返回 true，否则返回 false。");
        }
    }

    /**
     * nil? 语句
     * */
    public void Clj_list_is_nil(List<CljCell> lst, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        if (lst.size() == 2) {
            CljCell c = lst.get(1);
            if (c.getCljCellType() == CljCellType.nil) {
                rs.setCell(true);
                rs.setCljCellType(CljCellType.boolean_clj);
            } else {
                eval(c, funcHs, cljRecur, rs);
                if (rs.getCljCellType() == CljCellType.nil) {
                    rs.setCell(true);
                    rs.setCljCellType(CljCellType.boolean_clj);
                } else {
                    rs.setCell(false);
                    rs.setCljCellType(CljCellType.boolean_clj);
                }
            }
        } else {
            throw new Exception("使用建议：(nil? x) 如果 x 为 nil，则返回 true，否则返回 false。");
        }
    }

    /**
     * 执行 () 里面的内容
     * */
    public CljCell Clj_list(CljCell cell, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        List<CljCell> lst = (List<CljCell>) cell.getCell();
        if (!lst.isEmpty()) {
            CljCell c = lst.get(0);
            switch (c.getCljCellType()) {
                case defn:
                    Clj_list_defn(lst, funcHs, cljRecur, rs);
                    break;
                case symbol:
                    Clj_list_symbol(lst, funcHs, cljRecur, rs);
                    break;
                case addition:
                    Clj_list_addition(lst, funcHs, cljRecur, rs);
                    break;
                case subtraction:
                    Clj_list_subtraction(lst, funcHs, cljRecur, rs);
                    break;
                case multiplication:
                    Clj_list_multiplication(lst, funcHs, cljRecur, rs);
                    break;
                case division:
                    Clj_list_division(lst, funcHs, cljRecur, rs);
                    break;
                case apply:
                    Clj_list_apply(lst, funcHs, cljRecur, rs);
                    break;
                case cond:
                    Clj_list_cond(lst, funcHs, cljRecur, rs);
                    break;
                case if_clj:
                    Clj_list_if(lst, funcHs, cljRecur, rs);
                    break;
                case do_clj:
                    Clj_list_do(lst, funcHs, cljRecur, rs);
                    break;
                case and:
                    Clj_list_and(lst, funcHs, cljRecur, rs);
                    break;
                case or:
                    Clj_list_or(lst, funcHs, cljRecur, rs);
                    break;
                case equals_clj:
                    Clj_list_equals(lst, funcHs, cljRecur, rs);
                    break;
                case greater_than_clj:
                    Clj_list_greater_than(lst, funcHs, cljRecur, rs);
                    break;
                case less_than_clj:
                    Clj_list_less_than(lst, funcHs, cljRecur, rs);
                    break;
                case greater_equals_clj:
                    Clj_list_greater_equals(lst, funcHs, cljRecur, rs);
                    break;
                case less_equals_clj:
                    Clj_list_less_equals(lst, funcHs, cljRecur, rs);
                    break;
                case loop:
                    Clj_list_loop(lst, funcHs, cljRecur, rs);
                    break;
                case recur:
                    Clj_list_recur(lst, funcHs, cljRecur, rs);
                    break;
                case let:
                    Clj_list_let(lst, funcHs, cljRecur, rs);
                    break;
                case not:
                    Clj_list_not(lst, funcHs, cljRecur, rs);
                    break;
//                case nil:
//                    Clj_list_nil(lst, funcHs, cljRecur, rs);
//                    break;
                case is_nil:
                    Clj_list_is_nil(lst, funcHs, cljRecur, rs);
                    break;
                case println:
                    CljCell cljCell = lst.get(1);
                    if (cljCell.getCljCellType() == CljCellType.symbol) {
                        CljCell cljCell1 = funcHs.get(cljCell.getCell().toString());
                        System.out.println(cljCell1.getCell().toString());
                    } else {
                        System.out.println(lst.get(1).toString());
                    }
                    break;
            }
        }

        return rs;
    }

    public void my_list(CljCell cell, Hashtable<String, CljCell> funcHs, CljRecur cljRecur,CljCell rs) throws Exception {
        List<CljCell> lst = new ArrayList<>();
        for (CljCell c : (List<CljCell>)cell.getCell()) {
            //eval(c, funcHs, cljRecur, rs);
            lst.add(eval(c, funcHs, cljRecur, rs));
        }
        rs.setCell(lst);
        rs.setCljCellType(CljCellType.list);
    }

    /**
     * 执行
     * */
    public CljCell eval(CljCell cell, Hashtable<String, CljCell> funcHs, CljRecur cljRecur, CljCell rs) throws Exception {
        switch (cell.getCljCellType()) {
            case Clj_list:
                Clj_list(cell, funcHs, cljRecur, rs);
                break;
            case list:
                my_list(cell, funcHs, cljRecur, rs);
                break;
            case hash_table:
                break;
            case set:
                break;
            case symbol:
                if (funcHs != null && funcHs.containsKey(cell.getCell().toString()))
                {
                    CljCell cljCell = funcHs.get(cell.getCell().toString());
                    rs.setCell(cljCell.getCell());
                    rs.setCljCellType(cljCell.getCljCellType());
                } else {
                    //throw new Exception(cell.getCell().toString() + "不存在！");
                    rs.setCljCellType(CljCellType.nil);
                }
                break;
            case string_clj:
                //rs = cell;
                rs.setCell(cell.getCell());
                rs.setCljCellType(CljCellType.string_clj);
                break;
            case number_clj:
                //rs = cell;
                rs.setCell(cell.getCell());
                rs.setCljCellType(CljCellType.number_clj);
                break;
            case boolean_clj:
                rs = cell;
                break;
            case date_clj:
                rs = cell;
                break;
            case long_clj:
                rs = cell;
                break;
            case char_clj:
                rs = cell;
                break;
            case short_clj:
                rs = cell;
                break;
            case byte_clj:
                rs = cell;
                break;
            case double_clj:
                rs = cell;
                break;
            case float_clj:
                rs = cell;
                break;
        }
        return rs;
    }
}






































































